<?php
/**
 * 支付回调
 * User: peter
 * Date: 2018/7/2
 * Time: 下午5:12
 */

namespace app\activity\logic;


use app\model\ActivityOrder;
use app\model\ActivityOrderAttach;
use app\model\Bill;
use EasyWeChat\Factory;
use extend\Functions;
use extend\STATUS_CODE;
use think\facade\Env;

class PayNotify
{
    /**
     * @purpose 微信支付同步回调
     * @param string $order_no
     * @param int $uid
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\HttpException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public static function paySync(string $order_no): array
    {
        $order        = new ActivityOrder();
        $order_attach = new ActivityOrderAttach();
        $order->startTrans();
        $order_info = $order
            ->where([
                'order_no' => $order_no,
            ])
            ->lock(true)
            ->field('id,uid,status,pay_voucher')
            ->find();
        if (!$order_info) {
            $order->rollback();
            return Functions::result(
                STATUS_CODE::PARAMETER_ERROR,
                '无效的订单号!'
            );
        }
        if ($order_info->status === 99) {
            return Functions::result(
                STATUS_CODE::SUCCESS,
                '支付成功!'
            );
        }
        if ($order_info->status !== 1) {
            return Functions::result(
                STATUS_CODE::ORDER_STATUS_ERROR,
                '订单状态错误!'
            );
        }
        // 主动查询订单是否支付成功
        $app        = Factory::payment(config('wechat.payment.official_account'));
        $pay_result = $app->order->queryByOutTradeNumber($order_info->pay_voucher);
        if (
            $pay_result['return_code'] === 'SUCCESS' &&
            $pay_result['return_msg'] === 'OK' &&
            $pay_result['trade_state'] === 'SUCCESS' &&
            $pay_result['result_code'] === 'SUCCESS'
        ) {
            $pay_voucher  = $pay_result['out_trade_no'];
            $pay_voucher = explode('-', $pay_voucher);
            $order_no = $pay_voucher[0];
            $order_info = $order
                ->lock(true)
                ->with(['activity' => function($query) {
                    $query->field('id,title');
                }])
                ->where([
                    'order_no' => $order_no,
                    'uid'         => $order_info->uid,
                ])
                ->field('id,uid,activity_id,status,order_no,pay_voucher,create_at')
                ->find();
            if (!$order_info) {
                $order->rollback();
                return Functions::result(
                    STATUS_CODE::FAIL,
                    '订单未找到!'
                );
            }
            if ($order_info->status === 99) {
                $order->rollback();
                return Functions::result(
                    STATUS_CODE::SUCCESS,
                    '支付成功!'
                );
            }

            $update_data               = [];
            $update_data['status']     = 99;
            $update_data['pay_time']   = strtotime($pay_result['time_end']);
            $update_data['pay_money']  = $pay_result['cash_fee'];
            $update_data['pay_method'] = 1;
            $update_data['pay_no']     = $pay_result['transaction_id'];
            // 更新订单状态
            $order
                ->isUpdate(true)
                ->save($update_data, ['id' => $order_info->id]);
            // 更新订单附表状态
            $order_attach
                ->isUpdate(true)
                ->save(['status' => 99], ['order_id' => $order_info->id, 'status' => 1]);
            // 记录账单活动支付账单
            Bill::addToBill(
                $order_info->uid,
                1,
                $order_no,
                $pay_result['cash_fee'],
                1,
                '报名活动: 【'.$order_info->activity->title.'】'
            );
            $order->commit();
            return Functions::result();
        } else {
            return Functions::result(
                STATUS_CODE::PARAMETER_ERROR,
                $pay_result['trade_state_desc']
            );
        }
    }
    /**
     * @purpose app支付同步回调
     * @param string $order_no
     * @param int $uid
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\HttpException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public static function appPaySync(string $order_no, int $pay_type, int $uid): array
    {
        $order        = new ActivityOrder();
        $order_attach = new ActivityOrderAttach();
        $order->startTrans();
        $order_info = $order
            ->where([
                'order_no' => $order_no,
                'uid'      => $uid,
            ])
            ->lock(true)
            ->field('id,uid,status,pay_voucher,order_no')
            ->find();
        if (!$order_info) {
            $order->rollback();
            return Functions::result(
                STATUS_CODE::PARAMETER_ERROR,
                '无效的订单号!'
            );
        }
        if ($order_info->status === 99) {
            return Functions::result(
                STATUS_CODE::SUCCESS,
                '支付成功!'
            );
        }
        if ($order_info->status !== 1) {
            return Functions::result(
                STATUS_CODE::ORDER_STATUS_ERROR,
                '订单状态错误!'
            );
        }
        switch ($pay_type) {
            case 1: // 检测微信支付是否成功
                // 主动查询订单是否支付成功
                $app        = Factory::payment(config('wechat.payment.app'));
                $pay_result = $app->order->queryByOutTradeNumber($order_info->pay_voucher);
                if (
                    $pay_result['return_code'] === 'SUCCESS' &&
                    $pay_result['return_msg'] === 'OK' &&
                    $pay_result['trade_state'] === 'SUCCESS' &&
                    $pay_result['result_code'] === 'SUCCESS'
                ) {
                    $pay_voucher  = $pay_result['out_trade_no'];
                    $pay_voucher = explode('-', $pay_voucher);
                    $order_no = $pay_voucher[0];
                    $order_info = $order
                        ->with(['activity' => function($query) {
                            $query->field('id,title');
                        }])
                        ->where([
                            'order_no' => $order_no,
                            'uid'         => $uid,
                        ])
                        ->field('id,activity_id,uid,status,order_no,pay_voucher,create_at')
                        ->find();
                    if (!$order_info) {
                        $order->rollback();
                        return Functions::result(
                            STATUS_CODE::FAIL,
                            '订单未找到!'
                        );
                    }
                    if ($order_info->status === 99) {
                        $order->rollback();
                        return Functions::result(
                            STATUS_CODE::SUCCESS,
                            '支付成功!'
                        );
                    }

                    $update_data               = [];
                    $update_data['status']     = 99;
                    $update_data['pay_time']   = strtotime($pay_result['time_end']);
                    $update_data['pay_money']  = $pay_result['cash_fee'];
                    $update_data['pay_method'] = 1;
                    $update_data['pay_no']     = $pay_result['transaction_id'];
                    // 更新订单状态
                    $order
                        ->isUpdate(true)
                        ->save($update_data, ['id' => $order_info->id]);
                    // 更新订单附表状态
                    $order_attach
                        ->isUpdate(true)
                        ->save(['status' => 99], ['order_id' => $order_info->id, 'status' => 1]);
                    // 记录账单活动支付账单
                    Bill::addToBill(
                        $uid,
                        1,
                        $order_no,
                        $pay_result['cash_fee'],
                        1,
                        '报名活动:【'.$order_info->activity->title.'】'
                    );
                    $order->commit();
                    return Functions::result();
                } else if ($pay_result['return_code'] === 'FAIL') {
                    return Functions::result(
                        STATUS_CODE::PARAMETER_ERROR,
                        $pay_result['return_msg']
                    );
                } else {
                    return Functions::result(
                        STATUS_CODE::PARAMETER_ERROR,
                        $pay_result['trade_state_desc']
                    );
                }
                break;
            case 2:
                include Env::get('root_path'). 'extend/alipay/AopSdk.php';
                include Env::get('root_path'). 'extend/alipay/aop/request/AlipayTradeAppPayRequest.php';
                $aop                            = new \AopClient();
                $aop->gatewayUrl                = 'https://openapi.alipay.com/gateway.do';
                $aop->appId                     = config('alipay.app.appid');
                $aop->rsaPrivateKey             = config('alipay.app.private_key');
                $aop->format                    = 'json';
                $aop->charset                   = 'UTF-8';
                $aop->signType                  = 'RSA';
                $aop->alipayrsaPublicKey        = config('alipay.app.public_key');
                $content                        = [];
                $content['out_trade_no']        = $order_info->order_no;
                $request                        = new \AlipayTradeQueryRequest();
                $request->setBizContent(json_encode($content));
                $result                       = $aop->execute($request);
                $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";

                $result = $result->$responseNode;

                if ((int) $result->code !== 10000) {
                    return Functions::result(
                        $result->code,
                        $result->msg
                    );
                }
                // 交易支付成功
                if ($result->trade_status === 'TRADE_SUCCESS') {

                    $order_info = $order
                        ->with(['activity' => function($query) {
                            $query->field('id,title');
                        }])
                        ->where([
                            'order_no' => $result->out_trade_no,
                            'uid'         => $uid,
                        ])
                        ->field('id,uid,activity_id,status,order_no,pay_voucher,create_at')
                        ->find();
                    if (!$order_info) {
                        $order->rollback();
                        return Functions::result(
                            STATUS_CODE::FAIL,
                            '订单未找到!'
                        );
                    }
                    if ($order_info->status === 99) {
                        $order->rollback();
                        return Functions::result(
                            STATUS_CODE::SUCCESS,
                            '支付成功!'
                        );
                    }

                    $update_data               = [];
                    $update_data['status']     = 99;
                    $update_data['pay_time']   = time(); // strtotime($result->send_pay_date);
                    $update_data['pay_money']  = $result->total_amount * 100;
                    $update_data['pay_method'] = 3;
                    $update_data['pay_no']     = $result->trade_no;
                    // 更新订单状态
                    $order
                        ->isUpdate(true)
                        ->save($update_data, ['id' => $order_info->id]);
                    // 更新订单附表状态
                    $order_attach
                        ->isUpdate(true)
                        ->save(['status' => 99], ['order_id' => $order_info->id, 'status' => 1]);
                    $order->commit();

                    // 记录账单活动支付账单
                    Bill::addToBill(
                        $uid,
                        1,
                        $order_no,
                        $result->total_amount * 100,
                        3,
                        '报名活动:【'.$order_info->activity->title.'】'
                    );
                    return Functions::result();
                }
                return Functions::result(
                    STATUS_CODE::FAIL,
                    'STATUS: ['.$result->trade_status.'], CODE: ['.$result->code.']'
                );
                break;
            default:
                return Functions::result(
                    STATUS_CODE::PARAMETER_ERROR,
                    '未知的支付方式'
                );
                break;
        }
    }

}